/*
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2024-10-16 17:08:40
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2024-10-16 17:08:45
 * @FilePath: /react18-vite-admin/src/components/ui/CustomChart/utils.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */


export interface PieItemValue {
    name: string;
    value: number;
}

export const merge = <T = unknown>(...rest: T[]) => {
    let res: T | undefined;
    rest.forEach((item) => {
        if (res) {
            if (res.toString() === '[object Object]' || Array.isArray(res)) {
                const keys = Object.keys(item as Record<string, unknown>);
                const objectRes: Record<string, unknown> = res as Record<
                    string,
                    unknown
                >; // 严谨点这么写(res as Record<string, unknown> | unknown[])
                keys.forEach((key) => {
                    const itemProp = (item as Record<string, unknown>)[key]; // 严谨点这么写(item as Record<string, unknown>)[key] || (item as unknown[])[+key]
                    if (objectRes[key]) {
                        const objectResProp: NonNullable<unknown> = objectRes[
                            key
                        ] as NonNullable<unknown>;
                        if (
                            objectResProp.toString() === '[object Object]' ||
                            Array.isArray(objectResProp)
                        ) {
                            if (
                                itemProp &&
                                (itemProp.toString() === '[object Object]' ||
                                    Array.isArray(itemProp))
                            ) {
                                objectRes[key] = merge(
                                    objectResProp,
                                    itemProp as
                                        | Record<string, unknown>
                                        | unknown[]
                                );
                            } else {
                                objectRes[key] = itemProp;
                            }
                        } else {
                            objectRes[key] = itemProp;
                        }
                    } else {
                        objectRes[key] = itemProp;
                    }
                });
            } else {
                res = item;
                // throw new Error('合并内容必须是object或array');
            }
        } else {
            res = item;
        }
    });
    return res;
};

export const noop = () => {};

/**
 * 获取给定精度的数据，确保valueList中的百分比之和为1
 * 采用最大余数法
 * @param {number[]} valueList 所有数据的列表
 * @param {number} idx 数据的索引
 * @param {number} precision 精度
 * @return {number} 百分数
 */
export const getPercentWithPrecision = (
    valueList: number[],
    idx: number,
    precision: number
) => {
    if (!valueList[idx]) {
        return 0;
    }

    const sum = valueList.reduce((acc, val) => acc + (isNaN(val) ? 0 : val), 0);
    if (sum === 0) {
        return 0;
    }

    const digits = 10 ** precision;
    const votesPerQuota = valueList.map(
        (val) => ((isNaN(val) ? 0 : val) / sum) * digits * 100
    );
    const targetSeats = digits * 100;

    const seats = votesPerQuota.map((votes) => Math.floor(votes));
    let currentSum = seats.reduce((acc, val) => acc + val, 0);

    const remainder = votesPerQuota.map((votes, i) => votes - seats[i]);

    // Has remainding votes.
    while (currentSum < targetSeats) {
        // Find next largest remainder.
        let max = -Infinity; // Number.NEGATIVE_INFINITY;
        let maxId = 0;
        for (let i = 0, len = remainder.length; i < len; ++i) {
            if (remainder[i] > max) {
                max = remainder[i];
                maxId = i;
            }
        }

        // Add a vote to max remainder.
        seats[maxId] += 1;
        remainder[maxId] = 0;
        currentSum += 1;
    }

    return seats[idx] / digits;
};

// 防抖
export const debounce = (func: () => unknown, wait = 0, immediate = false) => {
    let timeout: number | null = null;
    return function (this: ThisType<any> | void, ...rest: any[]) {
        if (timeout !== null) window.clearTimeout(timeout);
        if (immediate) {
            const callNow = !timeout;
            timeout = window.setTimeout(() => {
                timeout = null;
            }, wait);
            if (callNow) func.apply<any, any, void>(this, rest);
        } else {
            timeout = window.setTimeout(() => {
                func.apply<any, any, void>(this, rest);
            }, wait);
        }
    };
};

// 节流
export const throttle = (
    func: () => unknown,
    wait: number,
    immediate = true
) => {
    let flag = false;
    return function (this: ThisType<any> | void, ...rest: any[]) {
        if (immediate) {
            if (!flag) {
                flag = true;
                func.apply<any, any, void>(this, rest);
                setTimeout(() => {
                    flag = false;
                }, wait);
            }
        } else if (!flag) {
            flag = true;
            // 如果是非立即执行，则在wait毫秒内的结束处执行
            setTimeout(() => {
                flag = false;
                func.apply<any, any, void>(this, rest);
            }, wait);
        }
    };
};
